/*
   Copyright 2010 Johan Hilding

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */


package org.johanhil.flygtider.provider;

import org.johanhil.flygtider.utils.ParseTime;

import android.text.format.Time;

public class FlightStatus {
	// TODO perhaps more of these identifiers are needed, esp. for the departing flights.
	public static final int NO_INFO = -1;
	public static final int DELAYED = 0;
	public static final int EARLY = 1;
	public static final int LANDED = 2;
	public static final int CANCELLED = 3;
	public static final int STARTED = 4;
	public static final int BOARDING = 5;
	public static final int ON_TIME = 6;
	public static final int STARTING = 7;
	public static final int INFO_COMING = 8;
	
	// we're just lucky that one keyword doesn't contain any other...
	private static final String LANDED_REGEX = ".*Landat.*|.*LANDAT.*";
	private static final String CANCELLED_REGEX = ".*Inställd.*";
	private static final String INFO_COMING_REGEX = "Nytt besked.*";
	// TODO what to do with "Utgång stängd"? It hasn't really started but it's a fair middle way.
	private static final String STARTED_REGEX = ".*Startat.*|.*Utgång stängd.*"; 
	private static final String BOARDING_REGEX = ".*Gå.*|Ombordstigning|Omedelbar avgång";

	private Time newTime; // the updated time
	private int status;
	
	private FlightStatus(int status, Time newTime)
	{
		this.status = status;
		this.newTime = newTime;
	}
	
	// TODO jesus clusterfuck, fix this. why is it static and akasjlfjerf.
	/**
	 * This is the builder of FlightStatus objects. I hate this.
	 */
	public static FlightStatus getStatus(FlightInfo flightInfo)
	{
		String note = flightInfo.getNotes();
		
		if (note == null || "".equals(note.trim()))
		{
			return new FlightStatus(NO_INFO,null);
		}
		
		// try to identify the status through the defined regexes.
		FlightStatus flightStatus = identifyByKeyword(note);
		
		if (flightStatus != null)
			return flightStatus;
		
		// when we get here it's either something we don't know about (meaning i forgot to add it to a regex) 
		// or it's information about how late/early the plane is.
		// for every time information the last five chars are "hh:mm"
		
		if (note.trim().length() <= 5) return new FlightStatus(NO_INFO,null);
				
		String newTimeString = note.trim().substring(note.trim().length()-5);
		String originalTimeString = flightInfo.getTime();
		
		Time newTime = ParseTime.parseHHMM(newTimeString);
		Time originalTime = ParseTime.parseHHMM(originalTimeString);
		
		if (newTime == null || originalTime == null)
		{
			return new FlightStatus(NO_INFO, null);
		}
				
		// now we have to subtract them both
		int status;
		
		if (originalTime.equals(newTime) || newTimeString.equals(originalTimeString))
		{
			status = ON_TIME;
		}
		else if (originalTime.before(newTime))
		{
			status = DELAYED;
		}
		else
		{
			// we might end up here by mistake if, as an example, originalTime is 23:25 and newTime is 00:25,
			// since we don't know about dates.
			// To mitigate this we only mark it as early if the difference is less than 2h.
			int diff = Math.abs((int)(newTime.toMillis(false) - originalTime.toMillis(false)));
			if (diff < 2*60*60*1000)
				status = EARLY;
			else
				status = DELAYED;
		}
				
		return new FlightStatus(status, newTime);
	}
	
	public Time getNewTime() {
		return newTime;
	}

	public int getStatus() {
		return status;
	}
	

	
	private static FlightStatus identifyByKeyword(String note)
	{
		if (note.matches(CANCELLED_REGEX))
		{
			return new FlightStatus(CANCELLED, null);
		}
		
		if (note.matches(LANDED_REGEX))
		{
			return new FlightStatus(LANDED, null);
		}
		
		if (note.matches(BOARDING_REGEX))
		{
			return new FlightStatus(BOARDING, null);
		}
		
		if (note.matches(STARTED_REGEX))
		{
			return new FlightStatus(STARTED, null);
		}
		
		if (note.matches(INFO_COMING_REGEX))
		{
		    return new FlightStatus(INFO_COMING, null);
		}
		
		return null;
	}
}
